﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Collections;
using System.Xml.Linq;
using System.Text.RegularExpressions;
using System.Drawing.Drawing2D;
using aoprinter.Model;

namespace aoprinter.IO
{
    internal class StyleCon
    {
        private Dictionary<string, Dictionary<string, object>> _dicBrush;
        private volatile static StyleCon _instance;
        private static readonly object _lockHelper = new object();
        private Pen _p;
        private Brush _b;
        private Font _f;
        private ModRegionStyle _whiteRegionStyle;

        private StyleCon()
        {
            _dicBrush = new Dictionary<string, Dictionary<string, object>>();
            _p = new Pen(Color.Black, 1);
            _b = new SolidBrush(Color.Black);
            _f = new Font("Times New Roman", 9, FontStyle.Regular);

            _whiteRegionStyle = new ModRegionStyle()
            {
                StyleID = "_White_Region_",
                BrushType = EnmBrush.SolidBrush,
                Colors = new Color[] { Color.White }
            };
        }

        public static StyleCon Instance
        {
            get
            {
                if (_instance == null)
                {
                    lock (_lockHelper)
                    {
                        _instance = new StyleCon();
                    }
                }
                return _instance;
            }
        }

        public ModRegionStyle WhiteRegion
        {
            get
            {
                return _whiteRegionStyle;
            }
        }

        public Pen GetPen(string reportID, ModLineStyle lineStyleMod)
        {
            if (lineStyleMod == null) return _p;
            if (!_dicBrush.ContainsKey(reportID))
            {
                Dictionary<string, object> dic = new Dictionary<string, object>();
                _dicBrush.Add(reportID, dic);
            }
            if (!_dicBrush[reportID].ContainsKey(lineStyleMod.StyleID))
            {
                Brush B = GetBrush(lineStyleMod);
                Pen p = new Pen(B);
                p.DashStyle = lineStyleMod.LineStyle;
                p.Width = lineStyleMod.Width;
                _dicBrush[reportID].Add(lineStyleMod.StyleID, p);
            }
            return _dicBrush[reportID][lineStyleMod.StyleID] as Pen;
        }

        public Brush GetBrush(string reportID, ModRegionStyle regionStyleMod)
        {
            if (regionStyleMod == null) return _b;
            if (!_dicBrush.ContainsKey(reportID))
            {
                Dictionary<string, object> dic = new Dictionary<string, object>();
                _dicBrush.Add(reportID, dic);
            }
            if (!_dicBrush[reportID].ContainsKey(regionStyleMod.StyleID))
            {
                _dicBrush[reportID].Add(regionStyleMod.StyleID, GetBrush(regionStyleMod));
            }
            return _dicBrush[reportID][regionStyleMod.StyleID] as Brush;
        }

        public TextCon GetTextCon(string reportID, ModTextStyle textStyleMod)
        {
            if (textStyleMod == null) return new TextCon() { Brush = _b, Font = _f };
            if (!_dicBrush.ContainsKey(reportID))
            {
                Dictionary<string, object> dic = new Dictionary<string, object>();
                _dicBrush.Add(reportID, dic);
            }
            if (!_dicBrush[reportID].ContainsKey(textStyleMod.StyleID))
            {
                textStyleMod.FontName = string.IsNullOrWhiteSpace(textStyleMod.FontName) ? _f.Name : textStyleMod.FontName;
                textStyleMod.FontSize = textStyleMod.FontSize > 0 ? textStyleMod.FontSize : _f.Size;
                Font F = new Font(textStyleMod.FontName, textStyleMod.FontSize, textStyleMod.TextFontStyle);
                _dicBrush[reportID].Add(textStyleMod.StyleID, new TextCon() { Brush = GetBrush(textStyleMod), Font = F });
            }
            return _dicBrush[reportID][textStyleMod.StyleID] as TextCon;
        }

        public void RemoveReport(string reportID)
        {
            _dicBrush.Remove(reportID);
        }

        private Brush GetBrush(ModRegionStyle style)
        {
            Brush B;
            switch (style.BrushType)
            {
                case EnmBrush.HatchBrush:
                    B = style.Colors == null || style.Colors.Length == 0 ? _b : new HatchBrush(style.HatchBrushStyle, style.Colors[0]);
                    break;
                case EnmBrush.LinearGradientBrush:
                    B = (style.Colors == null || style.Colors.Length < 2 || style.Points == null || style.Points.Length < 2) ?
                    _b : new LinearGradientBrush(style.Points[0], style.Points[1], style.Colors[0], style.Colors[1]);
                    break;
                case EnmBrush.PathGradientBrush:
                    if (style.Points == null || style.Colors.Length < 2)
                    {
                        B = _b;
                    }
                    else
                    {
                        PathGradientBrush pgb = new PathGradientBrush(style.Points);
                        pgb.InterpolationColors.Colors = style.Colors;
                        B = pgb;
                    }
                    break;
                case EnmBrush.SolidBrush:
                    B = style.Colors == null || style.Colors.Length == 0 ? _b : new SolidBrush(style.Colors[0]);
                    break;
                default:
                    B = _b;
                    break;
            }
            return B;
        }

        internal class TextCon
        {
            public Font Font;
            public Brush Brush;
        }
    }
}
